local tabFileProcessor = {}
local internalProcessor = {}
tabFileProcessor.fileProcessor = internalProcessor

function tabFileProcessor:tabToLua(str_tabFilePath, str_exportLuaFilePath)
    local str_TabFileName = internalProcessor:convLuaPathNameToFileName(str_tabFilePath)  --对文件路径进行提取文件名
    local str_ConfigName = str_TabFileName
    local tabTable = {}
    local _TblLines = internalProcessor:readFile(str_tabFilePath) --读取文件中每行的数据
    self:tabLinesToLuaTbl(tabTable, _TblLines, str_TabFileName)
    local outLuaTbl = {}
    internalProcessor:toLuaTab(str_ConfigName, tabTable, outLuaTbl)
    local str_LuaFileName = str_exportLuaFilePath.. str_ConfigName..".lua"
    internalProcessor:saveLuaFile(str_LuaFileName, outLuaTbl, str_ConfigName)
end

-- 判断字符串是否为空
local function isEmptyString(inStr_Value)
    if not inStr_Value then
        return true
    end
    return string.len(inStr_Value) <= 0
end

-- 字符串分割
local function split(inStr, inStr_Delim)
    if isEmptyString(inStr) then
        return {}
    end
    if (type(inStr_Delim) ~= 'string') or isEmptyString(inStr_Delim) then
        return { inStr }
    end
    local tbResult = {}
    local int_Start = 1
    while true do
        local int_Pos = string.find(inStr, inStr_Delim, int_Start, true) -- plain find
        if not int_Pos then
            break
        end
        table.insert(tbResult, string.sub(inStr, int_Start, int_Pos - 1))
        int_Start = int_Pos + string.len(inStr_Delim)
    end
    table.insert(tbResult, string.sub(inStr, int_Start))
    return tbResult
end

-- 处理Tab每行进行切分并构建table函数
function tabFileProcessor:tabLinesToLuaTbl(inOutTable, inTblLines, inStr_TabFileName)
    local int_StartIdx = 2
    local _ColNames = split(inTblLines[1], "\t")

    for i, _ in ipairs(inTblLines) do
        if (i >= int_StartIdx) then
            local _VTbl = split(inTblLines[i], "\t")
            internalProcessor:BuildTabTable(inOutTable, _VTbl[1], _ColNames, _VTbl,inStr_TabFileName)
        end
    end
end

-- 读取文件函数返回每行的数据
function internalProcessor:readFile(filePath)
    local file = io.open(filePath)
    assert(file,"file open failed - 文件打开失败! 请检查路径下是否有此文件:" ..filePath)       --如果文件不存在，则提示：文件打开失败
    local fileTab = {}
    local line = file:read()                           --读取文件中的单行内容存为另一个变量
    while line do                                      --当读取一行内容为真时
        -- print("get line 获取行内容：",line)              --打印读取的逐行line的内容
        table.insert(fileTab,line)                     --在fileTab表末尾插入读取line内容
        line = file:read()
    end
    file:close()
    return fileTab                                     --内容读取完毕，返回表
end


-- 保存lua文件
function internalProcessor:saveLuaFile(inFileName, inLuaTable, inConfigName)
    local luaStr = internalProcessor:tableToString(inLuaTable)
    local str_Metatable = nil
    luaStr = internalProcessor:wrapToLuaConfig(inConfigName, luaStr, str_Metatable)
    if (not internalProcessor:writefile(inFileName, luaStr)) then
        error("Write file failed: " .. inFileName)
        return false
    end
    return true
end


-- 写入到lua文件中
function internalProcessor:writefile(inFileName, luaStr)
    if io.open(inFileName) then              --如果文件为空则创建文件
        os.execute("type nul>"..inFileName) --创建文件
    end
    local file = io.open(inFileName, "w")
    if file then
        if file:write(luaStr) == nil then
            return false
        end
        io.close(file)
        print("File conversion succeeded --文件转换成功")
        return true
    else
        return false
    end
end

-- 截取文件名函数
function internalProcessor:convLuaPathNameToFileName(inPathName)
    local str_TFileName = string.reverse(inPathName)
    local int_RawPos = string.len(inPathName) - string.find(str_TFileName,"/")+1
    local str_FileName = string.sub(inPathName,int_RawPos+1, string.len(inPathName)-4)
    return str_FileName
end

-- 根据tab表创建出table表函数
function internalProcessor:BuildTabTable(inTabTable, inRowName, inColNames, inVTbl, inStr_TabFileName)
    if inRowName == "comment" or  inRowName == "Comment" then
        return
    end
    local index = tonumber(inRowName)
    if index == nil then
        error("inRowName is nil ,filename = "..inStr_TabFileName)
        return
    end
    if inTabTable[index] == nil then
        inTabTable[index] = {}
    else
        print("row id duplicated: filename = "..inStr_TabFileName.." row id "..inRowName)
    end
    for i, v in ipairs(inColNames) do
        if v ~= "n_ID" then
            inTabTable[index][v] = inVTbl[i]
        end
    end
end

function internalProcessor:toLuaTab(inCFGName, input2DTbl, inLuaTbl)
    for i, value in pairs(input2DTbl) do
        inLuaTbl[i] = {}
        for k, v in pairs(value) do
            internalProcessor:cellProcessor(inLuaTbl[i], inCFGName, i, k, v)
        end
    end
end

function internalProcessor:cellProcessor(inLuaTbl, inFN, inRN, inCN, inV)
    if inV == "nil" then
        return
    end
    local str_Left, str_Right = internalProcessor:splitString(inCN, "@",true)
    if (str_Left ~= nil and str_Right ~= nil) then
        local _MiddleValue = self:cellProcessor_OnMiddle(inLuaTbl,str_Right)
        internalProcessor:cellProcessor(_MiddleValue, inFN, inRN, str_Left, inV)
    else
        local str_finalKey, str_LeftKey = self:cellProcessor_GetFinalKey(inLuaTbl, inCN, inV)
        local str_FinalVal = self:cellProcessor_GetFinalValue(inLuaTbl, str_LeftKey, inV)
        if str_finalKey ~= nil then
            inLuaTbl[str_finalKey] = str_FinalVal
        end
    end
end

function internalProcessor:valueToString(inValue, inKey, inStr_Indent)
    if inKey == "SimpleInfo"  then
        return ""
    end
    local content
    if type(inValue) == "string" then
        local str_RealValue = inValue
        local int_LeftPos, int_RightPos = string.find(inValue, "_u@u_")
        if (int_LeftPos ~= nil) then
            str_RealValue = string.sub(inValue, int_RightPos+1, string.len(inValue))
            content = string.format('%s%s = %s,', inStr_Indent .. "  ", tostring(inKey), str_RealValue)
        else
            content = string.format('%s%s = "%s",', inStr_Indent .. "  ", tostring(inKey), str_RealValue)
        end
    else
        content = string.format("%s%s = %s,", inStr_Indent .. "  ", tostring(inKey), tostring(inValue))
    end
    return content
end


--把lua的table表内容转成str函数
local strcat = table.insert
local function pairsByKeys(t)
    local a = {}
    for n in pairs(t) do
        a[#a + 1] = n
    end
    table.sort(a)
    local i = 0
    return function()
        i = i + 1
        return a[i], t[a[i]]
    end
end

local str_Key = ""
-- 将lua的 table 转换成 项目内的 str模式
function internalProcessor:tableToString(inTable, inInt_Level)
    local resultTbl = {}
    inInt_Level = inInt_Level or 1
    local str_Indent = ""
    for i = 1, inInt_Level do
        str_Indent = str_Indent .. "  "
    end

    if str_Key ~= "" then
        strcat(resultTbl, "\r")
        strcat(resultTbl, str_Indent)
        strcat(resultTbl, str_Key)
        strcat(resultTbl," = {")
    else
        strcat(resultTbl,"\r")
        strcat(resultTbl,str_Indent)
        strcat(resultTbl,"{")
    end
    str_Key = ""
    for k, v in pairsByKeys(inTable) do
        if type(k) == "number" then
            k = "[" .. k .. "]"
        end

        if type(v) == "table" then
            str_Key = k
            local str_Tbl = internalProcessor:tableToString(v, inInt_Level + 1)
            strcat(resultTbl,"\r")
            strcat(resultTbl,str_Tbl)
        else
            local content = self:valueToString(v ,k ,str_Indent)
            strcat(resultTbl,"\r")
            strcat(resultTbl,content)
        end
    end
    if inInt_Level == 1 then
        strcat(resultTbl, "\r")
        strcat(resultTbl, str_Indent)
        strcat(resultTbl, "}")
    else
        strcat(resultTbl, "\r")
        strcat(resultTbl, str_Indent)
        strcat(resultTbl, "},")
    end
    return table.concat(resultTbl)
end

function internalProcessor:splitString(inString, inSplit, inBool_Reverse)
    local int_BegIdx, int_LastIdx
    if (inBool_Reverse) then
        local str_TS = string.reverse(inString)
        int_BegIdx, int_LastIdx = string.find(str_TS, inSplit)
        if int_BegIdx ~= nil and int_LastIdx ~= nil then
            int_BegIdx = string.len(inString) - int_BegIdx+1
            int_LastIdx = string.len(inString) - int_LastIdx+1
        end
    else
        int_BegIdx, int_LastIdx = string.find(inString, inSplit)
    end
    if (int_BegIdx == nil) then
        return nil, nil
    end
    local str_Left = string.sub(inString, 1, int_BegIdx - 1)
    local str_Right = string.sub(inString, int_LastIdx + 1, string.len(inString))
    return str_Left, str_Right
end

function internalProcessor:cellProcessor_OnMiddle(inLuaTbl,inStr_Right)
    local data_key = inStr_Right
    local int_Key = tonumber(inStr_Right)
    if int_Key ~= nil then
        data_key = int_Key
    end
    if inLuaTbl[data_key] == nil then
        inLuaTbl[data_key] = {}
    end
    return inLuaTbl[data_key]
end

function internalProcessor:cellProcessor_GetFinalValue(inLuaTbl, inStr_Left, inValue)
    local str_FinalVal
    if inStr_Left == "s" then
        str_FinalVal = inValue
    elseif inStr_Left == "n" then
        str_FinalVal = tonumber(inValue)
    elseif inStr_Left == "b" then
        if inValue == "FALSE" or inValue == "false" then
            str_FinalVal = false
        elseif inValue == "TRUE" or inValue == "true" then
            str_FinalVal = true

        end
    elseif inStr_Left == "u" then
        str_FinalVal = "_u@u_"..inValue
    end
    return str_FinalVal
end

function internalProcessor:cellProcessor_GetFinalKey(inLuaTbl, inCN, inV)
    local str_FinalWord = string.sub(inCN, string.len(inCN), string.len(inCN))
    local str_FinalKey
    if str_FinalWord == "_" then
        str_FinalKey = string.sub(inCN, 1, string.len(inCN)-1)
    else
        str_FinalKey = inCN
    end
    local str_Left, str_Right = internalProcessor:splitString(str_FinalKey, "_")
    local str_finalKey = str_Right
    local int_Key = tonumber(str_Right)
    if int_Key ~= nil then
        str_finalKey = int_Key
    end
    return str_finalKey, str_Left
end

-- 添加项目内配置进行字符串拼接
function internalProcessor:wrapToLuaConfig(inConfigName, inStr_Table, inStr_Metatable)
    local result = ""
    if inStr_Metatable then
        result = string.format("%s%s%s%s%s%s)",
            "local config = require(\"core.config\")\rlocal empty = {}\rconfig(\""
            ,inConfigName,"\",\rempty,\r",
            inStr_Table,",",
            inStr_Metatable)
    else
        result = string.format("%s%s%s%s)", "local config = require(\"core.config\")\rlocal empty = {}\rconfig(\""
            ,inConfigName,"\",\rempty,\r",
            inStr_Table)
    end
    return result
end

-- 对外暴露的方法
local function TabToLua(str_tabFilePath, str_exportLuaFilePath)
    tabFileProcessor:tabToLua(str_tabFilePath, str_exportLuaFilePath)
end

return TabToLua
